์ต์ ๋ฒ๋ธ ํจํด์ ๋ํ ์ข ํฉ ๊ฐ์ด๋๋ก ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ง์คํฐํ์ธ์. ํต์ฌ ๊ฐ๋ , ๊ตฌํ ๋ฐฉ๋ฒ ๋ฐ ๋ฐ์ํ ์ฑ ๊ตฌ์ถ์ ์ํ ์ค์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์์๋ณด์ธ์.
๋น๋๊ธฐ์์ ์ ์ฌ๋ ฅ ๋ฐํ: ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ๊ณผ ์ต์ ๋ฒ๋ธ ํจํด์ ๋ํ ์ฌ์ธต ํ๊ตฌ
ํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ์ ์ธ๊ณ์์๋ ๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ๋์์์ด ์์์ง๋๋ค. ์ฌ์ฉ์ ํด๋ฆญ, ๋คํธ์ํฌ ์์ฒญ, ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋, ์์คํ ์๋ฆผ ๋ฑ ๋ชจ๋ ๊ฒ์ด ์์ธกํ ์ ์์ด ๋์ฐฉํ๋ฉฐ, ์ด๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ด ์๊ตฌ๋ฉ๋๋ค. ์ ํต์ ์ธ ๋ช ๋ นํ ๋ฐ ์ฝ๋ฐฑ ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ๋น ๋ฅด๊ฒ ๋ณต์กํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ด ์ฝ๋๋ฅผ ์ด๋ํ๋ฉฐ, ์ข ์ข "์ฝ๋ฐฑ ์ง์ฅ"์ด๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค. ๋ฐ๋ก ์ด๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ ฅํ ํจ๋ฌ๋ค์ ์ ํ์ผ๋ก ๋ฑ์ฅํฉ๋๋ค.
์ด ํจ๋ฌ๋ค์์ ํต์ฌ์๋ ๋น๋๊ธฐ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฐ์ํ๊ณ ๊ฐ๋ ฅํ ์ถ์ํ์ธ ์ต์ ๋ฒ๋ธ ํจํด์ด ์์ต๋๋ค. ์ด ๊ฐ์ด๋์์๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ๊ณ , ์ต์ ๋ฒ๋ธ ํจํด์ ๋ช ํํ ์ค๋ช ํ๋ฉฐ, ํต์ฌ ๊ตฌ์ฑ ์์๋ฅผ ํ์ํ๊ณ , ๋ ํ๋ ฅ์ ์ด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋๋ฉฐ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํด ์ด๋ฅผ ๊ตฌํํ๊ณ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ์์ฐํ ๊ฒ์ ๋๋ค.
๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๋ ๋ฌด์์ธ๊ฐ์?
๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ฐ์ดํฐ ์คํธ๋ฆผ๊ณผ ๋ณ๊ฒฝ ์ฌํญ์ ์ ํ์ ๊ดํ ์ ์ธ์ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ๋๋ค. ๋ ๊ฐ๋จํ ๋งํด, ์๊ฐ ๊ฒฝ๊ณผ์ ๋ฐ๋ฅธ ์ด๋ฒคํธ์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ๋ฐ์ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋๋ค.
์คํ๋ ๋์ํธ๋ฅผ ์๊ฐํด ๋ณด์ธ์. ์
A1์ ๊ฐ์ ์
๋ฐ์ดํธํ๋ฉด ์
B1์ =A1 * 2์ ๊ฐ์ ์์์ด ์๋ ๊ฒฝ์ฐ, B1์ ์๋์ผ๋ก ์
๋ฐ์ดํธ๋ฉ๋๋ค. A1์ ๋ณ๊ฒฝ ์ฌํญ์ ์๋์ผ๋ก ๊ฐ์งํ๊ณ B1์ ์
๋ฐ์ดํธํ๋ ์ฝ๋๋ฅผ ์์ฑํ ํ์๊ฐ ์์ต๋๋ค. ๋จ์ํ ๋ ์ฌ์ด์ ๊ด๊ณ๋ฅผ ์ ์ธํฉ๋๋ค. B1์ A1์ ๋ฐ์ํ๋ ๊ฒ์
๋๋ค. ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ด ๊ฐ๋ ฅํ ๊ฐ๋
์ ๋ชจ๋ ์ข
๋ฅ์ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ ์ฉํฉ๋๋ค.
์ด ํจ๋ฌ๋ค์์ ์ข ์ข ๋ค์๊ณผ ๊ฐ์ ์์คํ ์ ์ค๋ช ํ๋ ๋ฐ์ํ ์ ์ธ๋ฌธ์ ๋ช ์๋ ์์น๊ณผ ์ฐ๊ด๋ฉ๋๋ค.
- ๋ฐ์์ฑ(Responsive): ์์คํ ์ ๊ฐ๋ฅํ ํ ์ฆ๊ฐ์ ์ผ๋ก ์๋ตํฉ๋๋ค. ์ด๋ ์ ์ฉ์ฑ๊ณผ ํ์ฉ์ฑ์ ์ด์์ ๋๋ค.
- ๋ณต์์ฑ(Resilient): ์์คํ ์ ์ฅ์ ๋ฐ์ ์์๋ ์๋ต์ฑ์ ์ ์งํฉ๋๋ค. ์ฅ์ ๋ ์ ์ฒด ์์คํ ์ ์์์ํค์ง ์๊ณ ๊ฒฉ๋ฆฌ๋๊ณ ์ฒ๋ฆฌ๋ฉ๋๋ค.
- ํ๋ ฅ์ฑ(Elastic): ์์คํ ์ ๋ณํํ๋ ์ํฌ๋ก๋์๋ ์๋ต์ฑ์ ์ ์งํฉ๋๋ค. ์ ๋ ฅ ์๋ ๋ณํ์ ๋ฐ๋ผ ํ ๋น๋ ๋ฆฌ์์ค๋ฅผ ๋๋ฆฌ๊ฑฐ๋ ์ค์ฌ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ๋ฉ์์ง ๊ตฌ๋(Message Driven): ์์คํ ์ ๋น๋๊ธฐ ๋ฉ์์ง ์ ๋ฌ์ ์์กดํ์ฌ ๊ตฌ์ฑ ์์ ๊ฐ์ ๊ฒฝ๊ณ๋ฅผ ์ค์ ํ๊ณ , ์ด๋ ๋์จํ ๊ฒฐํฉ, ๊ฒฉ๋ฆฌ ๋ฐ ์์น ํฌ๋ช ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
์ด๋ฌํ ์์น์ ๋๊ท๋ชจ ๋ถ์ฐ ์์คํ ์ ์ ์ฉ๋์ง๋ง, ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ฐ์ํ๋ค๋ ํต์ฌ ์์ด๋์ด๋ ์ต์ ๋ฒ๋ธ ํจํด์ด ์ ํ๋ฆฌ์ผ์ด์ ์์ค์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋๋ค.
์ต์ ๋ฒ ํจํด vs. ์ต์ ๋ฒ๋ธ ํจํด: ์ค์ํ ์ฐจ์ด์
๋ ๊น์ด ๋ค์ด๊ฐ๊ธฐ ์ ์, ๋ฐ์ํ ์ต์ ๋ฒ๋ธ ํจํด๊ณผ ๊ทธ ๊ณ ์ ์ ์ธ ์ ์ ์ธ "GoF(Gang of Four)"๊ฐ ์ ์ํ ์ต์ ๋ฒ ํจํด์ ๊ตฌ๋ณํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๊ณ ์ ์ ์ธ ์ต์ ๋ฒ ํจํด
GoF ์ต์ ๋ฒ ํจํด์ ๊ฐ์ฒด๋ค ๊ฐ์ ์ผ๋๋ค ์์กด์ฑ์ ์ ์ํฉ๋๋ค. ์ค์ฌ ๊ฐ์ฒด์ธ ์ฃผ์ฒด(Subject)๋ ์ต์ ๋ฒ(Observers)๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ข ์ ๊ฐ์ฒด ๋ชฉ๋ก์ ์ ์งํฉ๋๋ค. ์ฃผ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด, ์ผ๋ฐ์ ์ผ๋ก ์ต์ ๋ฒ์ ๋ฉ์๋ ์ค ํ๋๋ฅผ ํธ์ถํ์ฌ ๋ชจ๋ ์ต์ ๋ฒ์๊ฒ ์๋์ผ๋ก ์๋ฆฝ๋๋ค. ์ด๋ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ์์ ํํ ์ฌ์ฉ๋๋ ๊ฐ๋จํ๊ณ ํจ๊ณผ์ ์ธ "ํธ์(push)" ๋ชจ๋ธ์ ๋๋ค.
์ต์ ๋ฒ๋ธ ํจํด (๋ฐ์ํ ํ์ฅ)
๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ์ฌ์ฉ๋๋ ์ต์ ๋ฒ๋ธ ํจํด์ ๊ณ ์ ์ ์ธ ์ต์ ๋ฒ ํจํด์ ์งํํ์ ๋๋ค. ์ฃผ์ฒด๊ฐ ์ต์ ๋ฒ์๊ฒ ์ ๋ฐ์ดํธ๋ฅผ ํธ์ํ๋ ํต์ฌ ์์ด๋์ด๋ฅผ ๊ฐ์ ธ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ๊ณผ ์ดํฐ๋ ์ดํฐ ํจํด์ ๊ฐ๋ ์ผ๋ก ๊ฐํํ์ต๋๋ค. ์ฃผ์ ์ฐจ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์๋ฃ ๋ฐ ์ค๋ฅ: ์ต์ ๋ฒ๋ธ์ ๋จ์ํ ๊ฐ์ ํธ์ํ๋ ๊ฒ์ ๋์ด์ญ๋๋ค. ์คํธ๋ฆผ์ด ์๋ฃ๋์๊ฑฐ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์์ ์๋ฆด ์๋ ์์ต๋๋ค. ์ด๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ ์ ์๋ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ฐ์ฐ์๋ฅผ ํตํ ๊ตฌ์ฑ: ์ด๊ฒ์ด ์ง์ ํ ์ด๋ฅ๋ ฅ์
๋๋ค. ์ต์ ๋ฒ๋ธ์ (
map,filter,merge,debounceTime๊ณผ ๊ฐ์) ๋ฐฉ๋ํ ์ฐ์ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํจ๊ป ์ ๊ณต๋์ด ์คํธ๋ฆผ์ ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ๊ฒฐํฉ, ๋ณํ ๋ฐ ์กฐ์ํ ์ ์๋๋ก ํฉ๋๋ค. ์ฐ์ฐ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์ด๋ฅผ ํตํด ํ๋ฆ ๋๋ค. - ๊ฒ์ผ๋ฆ(Laziness): ์ต์ ๋ฒ๋ธ์ "๊ฒ์ผ๋ฆ ๋๋ค". ์ต์ ๋ฒ๊ฐ ๊ตฌ๋ ํ๊ธฐ ์ ๊น์ง๋ ๊ฐ์ ๋ฐฉ์ถํ๊ธฐ ์์ํ์ง ์์ต๋๋ค. ์ด๋ ํจ์จ์ ์ธ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
๋ณธ์ง์ ์ผ๋ก, ์ต์ ๋ฒ๋ธ ํจํด์ ๊ณ ์ ์ ์ธ ์ต์ ๋ฒ๋ฅผ ๋น๋๊ธฐ ์์ ์ ์ํ ์์ ํ ๊ธฐ๋ฅ์ ๊ฐ์ถ, ์กฐํฉ ๊ฐ๋ฅํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก ๋ฐ๊ฟ๋๋ค.
์ต์ ๋ฒ๋ธ ํจํด์ ํต์ฌ ๊ตฌ์ฑ ์์
์ด ํจํด์ ๋ง์คํฐํ๋ ค๋ฉด ๋ค ๊ฐ์ง ๊ทผ๋ณธ์ ์ธ ๊ตฌ์ฑ ์์๋ฅผ ์ดํดํด์ผ ํฉ๋๋ค. ์ด ๊ฐ๋ ๋ค์ ๋ชจ๋ ์ฃผ์ ๋ฐ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(RxJS, RxJava, Rx.NET ๋ฑ)์์ ์ผ๊ด์ ์ ๋๋ค.
1. ์ต์ ๋ฒ๋ธ(Observable)
์ต์ ๋ฒ๋ธ์ ์์ค์ ๋๋ค. ์ด๋ ์๊ฐ ๊ฒฝ๊ณผ์ ๋ฐ๋ผ ์ ๋ฌ๋ ์ ์๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ํ๋ ๋๋ค. ์ด ์คํธ๋ฆผ์ 0๊ฐ ๋๋ ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ ํฌํจํ ์ ์์ต๋๋ค. ์ฌ์ฉ์ ํด๋ฆญ ์คํธ๋ฆผ, HTTP ์๋ต, ํ์ด๋จธ์ ์ผ๋ จ์ ์ซ์ ๋๋ WebSocket์ ๋ฐ์ดํฐ์ผ ์ ์์ต๋๋ค. ์ต์ ๋ฒ๋ธ ์์ฒด๋ ์ฒญ์ฌ์ง์ผ ๋ฟ์ ๋๋ค. ๊ฐ์ ์์ฑํ๊ณ ์ ์กํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ ผ๋ฆฌ๋ฅผ ์ ์ํ์ง๋ง, ๋๊ตฐ๊ฐ ๋ฃ๊ณ ์์ง ์๋ ํ ์๋ฌด๊ฒ๋ ํ์ง ์์ต๋๋ค.
2. ์ต์ ๋ฒ(Observer)
์ต์ ๋ฒ๋ ์๋น์์ ๋๋ค. ์ต์ ๋ฒ๋ธ์ด ์ ๋ฌํ๋ ๊ฐ์ ๋ฐ์ํ๋ ๋ฐฉ๋ฒ์ ์๋ ์ฝ๋ฐฑ ๋ฉ์๋ ์งํฉ์ ๊ฐ์ง ๊ฐ์ฒด์ ๋๋ค. ํ์ค ์ต์ ๋ฒ ์ธํฐํ์ด์ค์๋ ์ธ ๊ฐ์ง ๋ฉ์๋๊ฐ ์์ต๋๋ค.
next(value): ์ด ๋ฉ์๋๋ ์ต์ ๋ฒ๋ธ์ด ํธ์ํ๋ ๊ฐ ์ ๊ฐ์ ๋ํด ํธ์ถ๋ฉ๋๋ค. ์คํธ๋ฆผ์next๋ฅผ 0๋ฒ ์ด์ ํธ์ถํ ์ ์์ต๋๋ค.error(err): ์ด ๋ฉ์๋๋ ์คํธ๋ฆผ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ํธ์ถ๋ฉ๋๋ค. ์ด ์ ํธ๋ ์คํธ๋ฆผ์ ์ข ๋ฃํ๋ฉฐ, ๋ ์ด์next๋๋completeํธ์ถ์ ์ด๋ฃจ์ด์ง์ง ์์ต๋๋ค.complete(): ์ด ๋ฉ์๋๋ ์ต์ ๋ฒ๋ธ์ด ๋ชจ๋ ๊ฐ์ ์ฑ๊ณต์ ์ผ๋ก ํธ์ ์๋ฃํ์ ๋ ํธ์ถ๋ฉ๋๋ค. ์ด ๋ํ ์คํธ๋ฆผ์ ์ข ๋ฃํฉ๋๋ค.
3. ๊ตฌ๋ (Subscription)
๊ตฌ๋
์ ์ต์ ๋ฒ๋ธ์ ์ต์ ๋ฒ์ ์ฐ๊ฒฐํ๋ ๋ค๋ฆฌ์
๋๋ค. ์ต์ ๋ฒ์ ํจ๊ป ์ต์ ๋ฒ๋ธ์ subscribe() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๊ตฌ๋
์ด ์์ฑ๋ฉ๋๋ค. ์ด ๋์์ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ํจ๊ณผ์ ์ผ๋ก "์ผ๋" ๊ฒ์
๋๋ค. ๊ตฌ๋
๊ฐ์ฒด๋ ์งํ ์ค์ธ ์คํ์ ๋ํ๋ด๋ฏ๋ก ์ค์ํฉ๋๋ค. ๊ฐ์ฅ ์ค์ํ ๊ธฐ๋ฅ์ unsubscribe() ๋ฉ์๋์ด๋ฉฐ, ์ด๋ฅผ ํตํด ์ฐ๊ฒฐ์ ํด์ ํ๊ณ , ๊ฐ ์์ ์ ์ค์งํ๊ณ , ๊ธฐ๋ณธ ๋ฆฌ์์ค(ํ์ด๋จธ ๋๋ ๋คํธ์ํฌ ์ฐ๊ฒฐ ๋ฑ)๋ฅผ ์ ๋ฆฌํ ์ ์์ต๋๋ค.
4. ์ฐ์ฐ์(Operators)
์ฐ์ฐ์๋ ๋ฐ์ํ ๊ตฌ์ฑ์ ํต์ฌ์ด์ ์ํผ์ ๋๋ค. ์ด๋ค์ ์ต์ ๋ฒ๋ธ์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ์๋กญ๊ณ ๋ณํ๋ ์ต์ ๋ฒ๋ธ์ ์ถ๋ ฅ์ผ๋ก ์์ฑํ๋ ์์ ํจ์์ ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋งค์ฐ ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ์กฐ์ํ ์ ์์ต๋๋ค. ์ฐ์ฐ์๋ ์ฌ๋ฌ ๋ฒ์ฃผ๋ก ๋๋ฉ๋๋ค.
- ์์ฑ ์ฐ์ฐ์: ์ฒ์๋ถํฐ ์ต์ ๋ฒ๋ธ์ ์์ฑํฉ๋๋ค(์:
of,from,interval). - ๋ณํ ์ฐ์ฐ์: ์คํธ๋ฆผ์์ ๋ฐฉ์ถ๋๋ ๊ฐ์ ๋ณํํฉ๋๋ค(์:
map,scan,pluck). - ํํฐ๋ง ์ฐ์ฐ์: ์์ค์์ ๊ฐ์ ๋ถ๋ถ ์งํฉ๋ง ๋ฐฉ์ถํฉ๋๋ค(์:
filter,take,debounceTime,distinctUntilChanged). - ์กฐํฉ ์ฐ์ฐ์: ์ฌ๋ฌ ์์ค ์ต์ ๋ฒ๋ธ์ ๋จ์ผ ์ต์ ๋ฒ๋ธ๋ก ๊ฒฐํฉํฉ๋๋ค(์:
merge,concat,zip). - ์ค๋ฅ ์ฒ๋ฆฌ ์ฐ์ฐ์: ์คํธ๋ฆผ์ ์ค๋ฅ๋ก๋ถํฐ ๋ณต๊ตฌํ๋ ๋ฐ ๋์์ ์ค๋๋ค(์:
catchError,retry).
์ต์ ๋ฒ๋ธ ํจํด์ ์ฒ์๋ถํฐ ๊ตฌํํ๊ธฐ
์ด๋ฌํ ๊ตฌ์ฑ ์์๋ค์ด ์ด๋ป๊ฒ ํจ๊ป ์๋ํ๋์ง ์ง์ ์ผ๋ก ์ดํดํ๊ธฐ ์ํด, ๋จ์ํ๋ ์ต์ ๋ฒ๋ธ ๊ตฌํ์ ๋ง๋ค์ด ๋ด ์๋ค. ๋ช ํ์ฑ์ ์ํด JavaScript/TypeScript ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๊ฒ ์ง๋ง, ๊ฐ๋ ์ ์ธ์ด์ ๊ตฌ์ ๋ฐ์ง ์์ต๋๋ค.
1๋จ๊ณ: ์ต์ ๋ฒ ๋ฐ ๊ตฌ๋ ์ธํฐํ์ด์ค ์ ์
๋จผ์ , ์๋น์์ ์ฐ๊ฒฐ ๊ฐ์ฒด์ ํํ๋ฅผ ์ ์ํฉ๋๋ค.
// The consumer of values delivered by an Observable.
interface Observer {
next: (value: any) => void;
error: (err: any) => void;
complete: () => void;
}
// Represents the execution of an Observable.
interface Subscription {
unsubscribe: () => void;
}
2๋จ๊ณ: ์ต์ ๋ฒ๋ธ ํด๋์ค ์์ฑ
์ ํฌ ์ต์ ๋ฒ๋ธ ํด๋์ค๋ ํต์ฌ ๋ก์ง์ ๋ด์ ๊ฒ์
๋๋ค. ์์ฑ์๋ ๊ฐ์ ์์ฑํ๋ ๋ก์ง์ ํฌํจํ๋ "๊ตฌ๋
์ ํจ์"๋ฅผ ๋ฐ์ต๋๋ค. subscribe ๋ฉ์๋๋ ์ต์ ๋ฒ๋ฅผ ์ด ๋ก์ง์ ์ฐ๊ฒฐํฉ๋๋ค.
class Observable {
// The _subscriber function is where the magic happens.
// It defines how to generate values when someone subscribes.
private _subscriber: (observer: Observer) => () => void;
constructor(subscriber: (observer: Observer) => () => void) {
this._subscriber = subscriber;
}
subscribe(observer: Observer): Subscription {
// The teardownLogic is a function returned by the subscriber
// that knows how to clean up resources.
const teardownLogic = this._subscriber(observer);
// Return a subscription object with an unsubscribe method.
return {
unsubscribe: () => {
teardownLogic();
console.log('Unsubscribed and cleaned up resources.');
}
};
}
}
3๋จ๊ณ: ์ฌ์ฉ์ ์ ์ ์ต์ ๋ฒ๋ธ ์์ฑ ๋ฐ ์ฌ์ฉ
์ด์ ์ ํฌ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋งค์ด ์ซ์๋ฅผ ๋ฐฉ์ถํ๋ ์ต์ ๋ฒ๋ธ์ ๋ง๋ค์ด ๋ด ์๋ค.
// Create a new Observable that emits numbers every second
const myIntervalObservable = new Observable((observer) => {
let count = 0;
const intervalId = setInterval(() => {
if (count >= 5) {
// After 5 emissions, we are done.
observer.complete();
clearInterval(intervalId);
} else {
observer.next(count);
count++;
}
}, 1000);
// Return the teardown logic. This function will be called on unsubscribe.
return () => {
clearInterval(intervalId);
};
});
// Create an Observer to consume the values.
const myObserver = {
next: (value) => console.log(`Received value: ${value}`),
error: (err) => console.error(`An error occurred: ${err}`),
complete: () => console.log('Stream has completed!')
};
// Subscribe to start the stream.
console.log('Subscribing...');
const subscription = myIntervalObservable.subscribe(myObserver);
// After 6.5 seconds, unsubscribe to clean up the interval.
setTimeout(() => {
subscription.unsubscribe();
}, 6500);
์ด๋ฅผ ์คํํ๋ฉด 0๋ถํฐ 4๊น์ง์ ์ซ์๊ฐ ๊ธฐ๋ก๋ ๋ค์, "์คํธ๋ฆผ์ด ์๋ฃ๋์์ต๋๋ค!"๋ผ๊ณ ๊ธฐ๋ก๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. unsubscribe ํธ์ถ์ ์๋ฃ ์ ์ ํธ์ถ๋์์ ๊ฒฝ์ฐ ์ธํฐ๋ฒ์ ์ ๋ฆฌํ์ฌ ์ ์ ํ ๋ฆฌ์์ค ๊ด๋ฆฌ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ค์ ์ฌ์ฉ ์ฌ๋ก ๋ฐ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ต์ ๋ฒ๋ธ์ ์ง์ ํ ํ์ ๋ณต์กํ ์ค์ ์๋๋ฆฌ์ค์์ ๋น์ ๋ฐํฉ๋๋ค. ๋ค์์ ๋ค์ํ ๋๋ฉ์ธ์ ๊ฑธ์น ๋ช ๊ฐ์ง ์์์ ๋๋ค.
ํ๋ก ํธ์๋ ๊ฐ๋ฐ (์: RxJS ์ฌ์ฉ)
- ์ฌ์ฉ์ ์
๋ ฅ ์ฒ๋ฆฌ: ๋ํ์ ์ธ ์์๋ ์๋ ์์ฑ ๊ฒ์ ์์์
๋๋ค.
keyup์ด๋ฒคํธ ์คํธ๋ฆผ์ ์์ฑํ๊ณ ,debounceTime(300)์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ํ์ดํ์ ๋ฉ์ถ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ ,distinctUntilChanged()๋ก ์ค๋ณต ์์ฒญ์ ๋ฐฉ์งํ๋ฉฐ,filter()๋ก ๋น ์ฟผ๋ฆฌ๋ฅผ ๊ฑธ๋ฌ๋ด๊ณ ,switchMap()์ผ๋ก API ํธ์ถ์ ์ํํ์ฌ ์ด์ ์ ๋ฏธ์๋ฃ ์์ฒญ์ ์๋์ผ๋ก ์ทจ์ํ ์ ์์ต๋๋ค. ์ด ๋ก์ง์ ์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ฉด ์์ฒญ๋๊ฒ ๋ณต์กํ์ง๋ง, ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ฉด ๊น๋ํ๊ณ ์ ์ธ์ ์ธ ์ฒด์ธ์ด ๋ฉ๋๋ค. - ๋ณต์กํ ์ํ ๊ด๋ฆฌ: Angular์ ๊ฐ์ ํ๋ ์์ํฌ์์ RxJS๋ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์ผ๋ฑ ์๋ฏผ์ ๋๋ค. ์๋น์ค๋ ์ํ๋ฅผ ์ต์ ๋ฒ๋ธ๋ก ๋ ธ์ถํ ์ ์์ผ๋ฉฐ, ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ์ด์ ๊ตฌ๋ ํ์ฌ ์ํ ๋ณ๊ฒฝ ์ ์๋์ผ๋ก ๋ค์ ๋ ๋๋ง๋ ์ ์์ต๋๋ค.
- ์ฌ๋ฌ API ํธ์ถ ์กฐ์ : ์ธ ๊ฐ์ ๋ค๋ฅธ ์๋ํฌ์ธํธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐํฉํด์ผ ํฉ๋๊น?
forkJoin(๋ณ๋ ฌ ์์ฒญ์ฉ) ๋๋concatMap(์์ฐจ ์์ฒญ์ฉ)๊ณผ ๊ฐ์ ์ฐ์ฐ์๊ฐ ์ด๋ฅผ ์ฌ์ํ๊ฒ ๋ง๋ญ๋๋ค.
๋ฐฑ์๋ ๊ฐ๋ฐ (์: RxJava, Project Reactor ์ฌ์ฉ)
- ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ: ์๋ฒ๋ ์ต์ ๋ฒ๋ธ์ ์ฌ์ฉํ์ฌ Kafka์ ๊ฐ์ ๋ฉ์์ง ํ ๋๋ WebSocket ์ฐ๊ฒฐ์์ ์ค๋ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ๋ํ๋ผ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ณํ, ๋ณด๊ฐ ๋ฐ ํํฐ๋งํ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฑฐ๋ ํด๋ผ์ด์ธํธ์ ๋ธ๋ก๋์บ์คํธํ ์ ์์ต๋๋ค.
- ํ๋ ฅ์ ์ธ ๋ง์ดํฌ๋ก์๋น์ค ๊ตฌ์ถ: ๋ฐ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ `retry` ๋ฐ `backpressure`์ ๊ฐ์ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ๋ฐฑํ๋ ์ ๋ ๋๋ฆฐ ์๋น์๊ฐ ๋น ๋ฅธ ์์ฐ์์๊ฒ ์๋๋ฅผ ๋ฆ์ถ๋๋ก ์ ํธ๋ฅผ ๋ณด๋ด ์๋น์๊ฐ ์๋๋นํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์ด๋ ์์ ์ ์ด๊ณ ํ๋ ฅ์ ์ธ ์์คํ ์ ๊ตฌ์ถํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
- ๋
ผ๋ธ๋กํน(Non-Blocking) API: Java ์ํ๊ณ์ Spring WebFlux(Project Reactor ์ฌ์ฉ)์ ๊ฐ์ ํ๋ ์์ํฌ๋ ์์ ํ ๋
ผ๋ธ๋กํน ์น ์๋น์ค๋ฅผ ๊ตฌ์ถํ ์ ์๋๋ก ํฉ๋๋ค. ์ปจํธ๋กค๋ฌ๋ `User` ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๋์ `Mono
`(0๊ฐ ๋๋ 1๊ฐ์ ํญ๋ชฉ ์คํธ๋ฆผ)๋ฅผ ๋ฐํํ์ฌ ๊ธฐ๋ณธ ์๋ฒ๊ฐ ๋ ์ ์ ์ค๋ ๋๋ก ํจ์ฌ ๋ ๋ง์ ๋์ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํฉ๋๋ค.
์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ด๊ฒ์ ์ฒ์๋ถํฐ ๊ตฌํํ ํ์๋ ์์ต๋๋ค. ๊ฑฐ์ ๋ชจ๋ ์ฃผ์ ํ๋ซํผ์์ ๊ณ ๋๋ก ์ต์ ํ๋๊ณ ๊ฒ์ฆ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- RxJS: JavaScript ๋ฐ TypeScript๋ฅผ ์ํ ์ต๊ณ ์ ๊ตฌํ์ฒด์ ๋๋ค.
- RxJava: Java ๋ฐ Android ๊ฐ๋ฐ ์ปค๋ฎค๋ํฐ์ ์ฃผ๋ฅ์ ๋๋ค.
- Project Reactor: Spring Framework์ ๋ฐ์ํ ์คํ์ ๊ธฐ๋ฐ์ ๋๋ค.
- Rx.NET: ReactiveX ์ด๋์ ์์ํ ์ค๋ฆฌ์ง๋ Microsoft ๊ตฌํ์ฒด์ ๋๋ค.
- RxSwift / Combine: Apple ํ๋ซํผ์์์ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ํ ํต์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
์ฐ์ฐ์์ ํ: ์ค์ฉ์ ์ธ ์์
์์ ์ธ๊ธํ ์๋ ์์ฑ ๊ฒ์ ์์ ์์๋ฅผ ํตํด ์ฐ์ฐ์์ ์กฐํฉ ๋ฅ๋ ฅ์ ์ค๋ช ํด ๋ด ์๋ค. RxJS ์คํ์ผ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ๊ฒ์ ๋๋ค.
// 1. Get a reference to the input element
const searchInput = document.getElementById('search-box');
// 2. Create an Observable stream of 'keyup' events
const keyup$ = fromEvent(searchInput, 'keyup');
// 3. Build the operator pipeline
keyup$.pipe(
// Get the input value from the event
map(event => event.target.value),
// Wait for 300ms of silence before proceeding
debounceTime(300),
// Only continue if the value has actually changed
distinctUntilChanged(),
// If the new value is different, make an API call.
// switchMap cancels previous pending network requests.
switchMap(searchTerm => {
if (searchTerm.length === 0) {
// If input is empty, return an empty result stream
return of([]);
}
// Otherwise, call our API
return api.search(searchTerm);
}),
// Handle any potential errors from the API call
catchError(error => {
console.error('API Error:', error);
return of([]); // On error, return an empty result
})
)
.subscribe(results => {
// 4. Subscribe and update the UI with the results
updateDropdown(results);
});
์ด ์งง๊ณ ์ ์ธ์ ์ธ ์ฝ๋ ๋ธ๋ก์ ์๋ ์ ํ, ์ค๋ณต ์ ๊ฑฐ, ์์ฒญ ์ทจ์์ ๊ฐ์ ๊ธฐ๋ฅ์ ํฌํจํ๋ ๋งค์ฐ ๋ณต์กํ ๋น๋๊ธฐ ์ํฌํ๋ก์ฐ๋ฅผ ๊ตฌํํฉ๋๋ค. ์ด๋ฅผ ์ ํต์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฌ์ฑํ๋ ค๋ฉด ํจ์ฌ ๋ ๋ง์ ์ฝ๋์ ์๋์ ์ธ ์ํ ๊ด๋ฆฌ๊ฐ ํ์ํ์ฌ ์ฝ๊ณ ๋๋ฒ๊น ํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง ๊ฒ์ ๋๋ค.
๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ธ์ ์ฌ์ฉํ๊ณ (์ธ์ ์ฌ์ฉํ์ง ๋ง์์ผ ํ ์ง)
์ด๋ค ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ๋ ๋ง๋ฅ ํด๊ฒฐ์ฑ ์ ์๋๋๋ค. ๊ทธ ์ฅ๋จ์ ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ ํฉํ ๊ฒฝ์ฐ:
- ์ด๋ฒคํธ๊ฐ ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ : ์ฌ์ฉ์ ์ธํฐํ์ด์ค, ์ค์๊ฐ ๋์๋ณด๋, ๋ณต์กํ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์์คํ ์ด ์ฃผ์ ํ๋ณด์ ๋๋ค.
- ๋น๋๊ธฐ ์ค์ฌ ๋ก์ง: ์ฌ๋ฌ ๋คํธ์ํฌ ์์ฒญ, ํ์ด๋จธ ๋ฐ ๊ธฐํ ๋น๋๊ธฐ ์์ค๋ฅผ ์กฐ์ ํด์ผ ํ ๋ ์ต์ ๋ฒ๋ธ์ ๋ช ํ์ฑ์ ์ ๊ณตํฉ๋๋ค.
- ์คํธ๋ฆผ ์ฒ๋ฆฌ: ๊ธ์ต ํฐ์ปค์์ IoT ์ผ์ ๋ฐ์ดํฐ์ ์ด๋ฅด๊ธฐ๊น์ง ์ฐ์์ ์ธ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ๋ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํฉ๋๋ค.
๋์์ ๊ณ ๋ คํด์ผ ํ ๊ฒฝ์ฐ:
- ๋ก์ง์ด ๋จ์ํ๊ณ ๋๊ธฐ์ ์ธ ๊ฒฝ์ฐ: ๊ฐ๋จํ๊ณ ์์ฐจ์ ์ธ ์์ ์ ๊ฒฝ์ฐ, ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ค๋ฒํค๋๋ ๋ถํ์ํฉ๋๋ค.
- ํ์ด ์ต์ํ์ง ์์ ๊ฒฝ์ฐ: ํ์ต ๊ณก์ ์ด ๊ฐํ๋ฆ ๋๋ค. ์ ์ธ์ , ํจ์ํ ์คํ์ผ์ ๋ช ๋ นํ ์ฝ๋์ ์ต์ํ ๊ฐ๋ฐ์์๊ฒ๋ ์ด๋ ค์ด ์ ํ์ด ๋ ์ ์์ต๋๋ค. ํธ์ถ ์คํ์ด ๋ ์ง์ ์ ์ด๋ฏ๋ก ๋๋ฒ๊น ๋ ๋ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
- ๋ ๊ฐ๋จํ ๋๊ตฌ๋ก ์ถฉ๋ถํ ๊ฒฝ์ฐ: ๋จ์ผ ๋น๋๊ธฐ ์์ ์ ๊ฒฝ์ฐ, ๊ฐ๋จํ Promise ๋๋ `async/await`๊ฐ ๋ ๋ช ํํ๊ณ ์ถฉ๋ถํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์์ ์ ์ ํฉํ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ธ์.
๊ฒฐ๋ก
์ต์ ๋ฒ๋ธ ํจํด์ผ๋ก ๊ตฌ๋๋๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋น๋๊ธฐ ์์คํ ์ ๋ณต์ก์ฑ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฒฌ๊ณ ํ๊ณ ์ ์ธ์ ์ธ ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฒคํธ์ ๋ฐ์ดํฐ๋ฅผ ์กฐํฉ ๊ฐ๋ฅํ ์คํธ๋ฆผ์ผ๋ก ์ฒ๋ฆฌํจ์ผ๋ก์จ, ๊ฐ๋ฐ์๋ ๋ ๊น๋ํ๊ณ ์์ธก ๊ฐ๋ฅํ๋ฉฐ ํ๋ ฅ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
์ ํต์ ์ธ ๋ช ๋ นํ ํ๋ก๊ทธ๋๋ฐ์์ ์ฌ๊ณ ๋ฐฉ์์ ์ ํ์ด ํ์ํ์ง๋ง, ๋ณต์กํ ๋น๋๊ธฐ ์๊ตฌ ์ฌํญ์ด ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๊ทธ ํฌ์๊ฐ ํฐ ์ด๋์ ๊ฐ์ ธ์ต๋๋ค. ์ต์ ๋ฒ๋ธ, ์ต์ ๋ฒ, ๊ตฌ๋ , ์ฐ์ฐ์๋ผ๋ ํต์ฌ ๊ตฌ์ฑ ์์๋ฅผ ์ดํดํจ์ผ๋ก์จ ์ด ๊ฐ๋ ฅํ ํ์ ํ์ฉํ ์ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ์ ํํ ํ๋ซํผ์ ๋ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํ๊ณ , ๊ฐ๋จํ ์ฌ์ฉ ์ฌ๋ก๋ถํฐ ์์ํ์ฌ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด ์ ๊ณตํ ์ ์๋ ํํ๋ ฅ ์๊ณ ์ฐ์ํ ์๋ฃจ์ ์ ์ ์ง์ ์ผ๋ก ๋ฐ๊ฒฌํด ๋ณด์๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.